package com.macro.mall.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.macro.mall.demo.dto.DocSaveDto;
import com.macro.mall.demo.dto.DocSearchRequest;
import com.macro.mall.demo.dto.OrderInfo;
import com.macro.mall.demo.service.EsDocService;
import com.macro.mall.demo.service.EsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author：尚志豪
 * @Package：com.macro.mall.demo.service.impl
 * @Project：mall-swarm-B
 * @name：EsDocServiceImpl
 * @Date：2024/10/25 20:38
 */

@Service
@Slf4j
public class EsDocServiceImpl implements EsDocService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private EsService esService;


    @Override
    public void save(DocSaveDto docSaveDto) {
        List<Map<String, Object>> datas = docSaveDto.getDatas();
        String idField = docSaveDto.getIdField();

        if (CollectionUtils.isEmpty(datas)){
            throw new RuntimeException("文档数据不能为空");
        }

        //构建一个批量请求
        BulkRequest bulkRequest = new BulkRequest();

        //为每个文档构建 IndexRequest
        for (Map<String, Object> data : datas) {

            IndexRequest indexRequest = new IndexRequest(docSaveDto.getIndexName());

            //校检是否自增id
            if (StringUtils.isNotBlank(idField)){
                String idValue = (String) data.get(idField);
                //手动指定id
                indexRequest.id(idValue);
            }

            //给source赋值
            indexRequest.source(data, XContentType.JSON);
            //设置文档内容
            bulkRequest.add(indexRequest);
        }

        //执行批量添加
        if (bulkRequest.numberOfActions()>0){
            try {
                BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
                if (bulkResponse.hasFailures()){
                    //todo 调用删除，删除本次所有数据
                    delete(docSaveDto.getIndexName());
                    log.error("批量插入数据失败:{}",bulkResponse.buildFailureMessage());
                }else {
                    log.info("成功批量插入{}个文档",bulkResponse.getItems().length);
                }
            } catch (IOException e) {
                log.error("批量插入数据时发生异常：{}",e.getMessage(),e);
            }
        }else {
            log.warn("没有有效文档可插入");
        }
    }

    @Override
    public void delete(String indexName) {
        if (StringUtils.isEmpty(indexName)){
            throw new RuntimeException("索引不存在:"+indexName);
        }

        //创建
        DeleteByQueryRequest queryRequest = new DeleteByQueryRequest(indexName);
        queryRequest.setQuery(QueryBuilders.matchAllQuery());

        //删除
        try {
            restHighLevelClient.deleteByQuery(queryRequest,RequestOptions.DEFAULT);
            log.info("批量删除成功");
        } catch (IOException e) {
            log.error("批量删除数据时发生异常:{}",e.getMessage(),e);
        }
    }

    @Override
    public List source(DocSearchRequest docSearchRequest) {
        List list = new ArrayList<>();
        OrderInfo orderInfo = docSearchRequest.getOrderInfo();

        try {
            SearchRequest searchRequest = new SearchRequest(docSearchRequest.getIndexName());

            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            //查询
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

            //搜索
            if (docSearchRequest.getQueryInfo()!=null){
                docSearchRequest.getQueryInfo().getFields().forEach(bbb->{
                    boolQueryBuilder.should(QueryBuilders.matchQuery(bbb,docSearchRequest.getQueryInfo().getKeyWord()));
                });
            }


            //分页
            if (docSearchRequest.getPageNum()!=null){
                searchSourceBuilder.from((docSearchRequest.getPageNum()-1) * docSearchRequest.getPageSize());
            }
            if (docSearchRequest.getPageSize()!=null){
                searchSourceBuilder.size(docSearchRequest.getPageSize());
            }

            if (orderInfo.getOrderType()!=null && orderInfo.getOrderField()!=null){
                if (orderInfo.getOrderType().equals("desc")){
                    searchSourceBuilder.sort(orderInfo.getOrderField(), SortOrder.DESC);
                }

                if (orderInfo.getOrderType().equals("asc")){
                    searchSourceBuilder.sort(orderInfo.getOrderField(),SortOrder.ASC);
                }
            }

            searchRequest.source(searchSourceBuilder);
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            SearchHits hits = search.getHits();
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                list.add(JSON.parseObject(sourceAsString));
            }
        } catch (Throwable  e) {
            throw new RuntimeException(e);
        }
        return list;
    }
}
